#include "CommEngine.h"
#include <iostream>
#include <string.h>

using namespace std;
#ifdef WINDOWS
#pragma comment(lib,"ws2_32.lib") 
#endif



/************************************************************************/
/*                                                                      */
/************************************************************************/
int CommEngine::CommInitSock()
{
	m_cfg = new cfgData;	
	char host[MAX_NAMEBUF];
	if(gethostname(host, sizeof(host)) == SOCKET_ERROR)
	{
		cout<<"user name error"<<endl;	
		return -1;
	}
	strcpy(m_cfg->hostname, host);
	
	unsigned long size = sizeof(m_cfg->username);
#ifdef WINDOWS
	GetUserName(m_cfg->username, &size);
#else
	getlogin_r(m_cfg->username, size);
#endif 
	m_tcpsock = socket(AF_INET, SOCK_STREAM, 0);
	if(m_tcpsock < 0)
	{
		perror("m_tcpsock");
		return -1;
	}
	cout<<"m_tcpsock socket successfully"<<endl;
	m_udpsock = socket(AF_INET, SOCK_DGRAM, 0);
	if(m_udpsock < 0)
	{
		perror("m_udpsock");
		return -1;		
	}
	cout<<"m_udpsock socket successfully"<<endl;
	return 0;
}





/************************************************************************/
/*                                                                      */
/************************************************************************/
int CommEngine::CommBindTCP(struct FFAddress addr, unsigned short portno)
{
	addr.host.sin_family = AF_INET;
	addr.host.sin_port = htons(portno);

#ifdef WINDOWS	
	addr.host.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
#else
	addr.host.sin_addr.s_addr = htonl(INADDR_ANY);
#endif

	if(bind(m_tcpsock,(struct sockaddr *)(&(addr.host)), sizeof(addr.host)) < 0)
	{
		cout<<("bind m_tcpsock error")<<endl;
#ifdef WINDOWS
		cout<<WSAGetLastError()<<endl;
#endif
		return -1;
	}
	cout<<"m_tcpsock bind successfully"<<endl;
	
	return 0;
}





/************************************************************************/
/*                                                                      */
/************************************************************************/
int CommEngine::CommBindUDP(struct FFAddress addr, unsigned short portno)
{
	addr.host.sin_family = AF_INET;
	addr.host.sin_port = htons(portno);

#ifdef WINDOWS
	addr.host.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
#else
	addr.host.sin_addr.s_addr = htonl(INADDR_ANY);
#endif

	if(bind(m_udpsock,(struct sockaddr *)(&(addr.host)), sizeof(addr.host))<0)
	{
		cout<<"bind m_udpsock error"<<endl;
#ifdef  WINDOWS
		cout<<WSAGetLastError()<<endl;
#endif
		return -1;
	}
	cout<<"m_udpsock bind successfully"<<endl;
	
	return 0;
}






/************************************************************************/
/*                                                                      */
/************************************************************************/
int CommEngine::CommBroadUDPSend(int portno, const char *buf)
{
	int len = strlen(buf) +1;
	
	struct sockaddr_in	addr;
	
	memset(&addr, 0, sizeof(addr));
	addr.sin_family				= AF_INET;
	addr.sin_port				= htons(portno);

#ifdef WINDOWS
	addr.sin_addr.S_un.S_addr	= -1;
#else
	addr.sin_addr.s_addr = -1;
#endif
	sendto(m_udpsock, buf, len, 0, (LPSOCKADDR)&addr, sizeof(addr));
	cout<<"boradcast ok"<<endl;
	return 0;
}





/************************************************************************/
/*                                                                      */
/************************************************************************/
int CommEngine::CommUDPSend(unsigned long hostaddr, int portno, const char *buf)
{
	int len = strlen(buf) +1;
	
	struct sockaddr_in	addr;
	
	memset(&addr, 0, sizeof(addr));
	addr.sin_family				= AF_INET;
	addr.sin_port				= htons(portno);

#ifdef WINDOWS
	addr.sin_addr.S_un.S_addr	= hostaddr;
#else
	addr.sin_addr.s_addr = hostaddr;
#endif

	sendto(m_udpsock, buf, len, 0, (LPSOCKADDR)&addr, sizeof(addr));
	
	cout<<"CommUDPSend ok"<<endl;
	
	return 0;
}



/************************************************************************/
/*                                                                      */
/************************************************************************/
int CommEngine::CommListen()
{
	if(listen(m_tcpsock, 10) < 0)
	{
		perror("m_tcpsock listen");
		return -1;
	}
	else
	{
		cout<<"listen successful"<<endl;
	}
	return 0;
}



/************************************************************************/
/*                                                                      */
/************************************************************************/
void CommEngine::CommCleanUpSock()
{
	CommCloseTCPSock();
	CommCloseUDPSock();
#ifdef WINDOWS
	WSACleanup();
#endif

}



/************************************************************************/
/*                                                                      */
/************************************************************************/
int CommEngine::CommAccept(struct sockaddr_in &tcpaddr)
{
	
	SOCKET client_tcp;
	int len = sizeof(tcpaddr);
	client_tcp = accept(m_tcpsock,(struct sockaddr *)&tcpaddr,&len);
	if(client_tcp == INVALID_SOCKET)
	{
		cout<<"accept tcp ---------error"<<endl;
		return INVALID_SOCKET;
	}
	else
	{
		cout<<"accept tcp ---------ok"<<endl;
		return client_tcp;
	}	
}





/************************************************************************/
/*                                                                      */
/************************************************************************/
void CommEngine::CommCloseTCPSock()
{
	if (m_tcpsock != INVALID_SOCKET)
	{
#ifdef WINDOWS
		closesocket(m_tcpsock);
#else 
		close(m_tcpsock);
#endif
		m_tcpsock = INVALID_SOCKET;
	}
}





/************************************************************************/
/*                                                                      */
/************************************************************************/
void CommEngine::CommCloseUDPSock()
{
	if (m_udpsock != INVALID_SOCKET)
	{
#ifdef WINDOWS
		closesocket(m_udpsock);
#else 
		close(m_udpsock);
#endif
		m_udpsock = INVALID_SOCKET;
	}
}




/************************************************************************/
/*                                                                      */
/************************************************************************/
int CommEngine::CommConnect(unsigned long faraddr,int port)
{
	//iconnect(m_tcpsock
	struct sockaddr_in tcpaddr;
	tcpaddr.sin_port = port;
	tcpaddr.sin_family = AF_INET;
	tcpaddr.sin_addr.S_un.S_addr = faraddr;
	int len = sizeof(tcpaddr);
	return connect(m_tcpsock,(struct sockaddr*)&tcpaddr,len);
}




/************************************************************************/
/*                                                                      */
/************************************************************************/
int CommEngine::CommUdpSelect(fd_set *rdfds,timeval *timeout)
{
	
	return select(m_udpsock+1,rdfds,NULL,NULL,timeout);
}




/************************************************************************/
/*                                                                      */
/************************************************************************/
#ifdef WINDOWS
void CommEngine::RegisterRecvThread(void (*p)(LPVOID),void *q)
#else
void CommEngine::RegisterRecvThread(void* (*p)(LPVOID),void *q)
#endif
{
	recvthread = p;
	arg =(Protocol*)q;
}




/************************************************************************/
/*                                                                      */
/************************************************************************/
void CommEngine::CommStartThread()
{
	static struct threadArg tharg;
	tharg.udp_sock = m_udpsock;
	tharg.pro = arg;
	cout<<"thread start () ok "<<endl;
#ifdef WINDOWS
	_beginthread(recvthread,0,(void *)&tharg);
#else
	pthread_t tid;
	pthread_create(&tid,NULL,recvthread,(void *)&tharg);
#endif
	cout<<"start thread"<<endl;
}





/************************************************************************/
/*                                                                      */
/************************************************************************/

void CommEngine::CommStartSock()
{
#ifdef WINDOWS	
	WORD wVersionRequested;
	wVersionRequested = MAKEWORD(2, 2);
	WSADATA wsaData;
	WSAStartup( wVersionRequested, &wsaData);
#endif	
}

/************************************************************************/
/*                                                                      */
/************************************************************************/

bool CommEngine::CommUdpRecv(struct RecvBuf *buf)
{
	struct sockaddr_in udpsaddr;
#ifdef WINDOWS
	int bufsize= sizeof(udpsaddr);
#else
	socklen_t bufsize=sizeof(udpsaddr);
#endif
	
	buf->size=recvfrom(m_udpsock,buf->msgBuf,sizeof(buf->msgBuf)-1,0,(struct sockaddr *)&udpsaddr,&bufsize);
	if(buf->size == 0)
		return FALSE;
	buf->portno = udpsaddr.sin_port;
	buf->msgBuf[buf->size]=0;
#ifdef WINDOWS
	buf->addr=udpsaddr.sin_addr.S_un.S_addr;
#else
	buf->addr = udpsaddr.sin_addr.s_addr;
#endif
	cout<<"-------------ip-------------------"<<buf->addr<<endl;
	return FALSE;

}


